home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume14 / mush6.0 / part07 < prev    next >
Encoding:
Internet Message Format  |  1988-04-12  |  41.8 KB

  1. From: island!argv@sun.com (Dan Heller)
  2. Subject: Mail User's Shell, version 6.0
  3.  
  4. #! /bin/sh
  5. # This is a shell archive.  Remove anything before this line, then unpack
  6. # it by saving it into a file and typing "sh file".  To overwrite existing
  7. # files, type "sh file -c".  You can also feed this as standard input via
  8. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  9. # will see the following message at the end:
  10. #        "End of archive 7 (of 14)."
  11. # Contents:  curses.c msgs.c
  12. # Wrapped by rsalz@fig.bbn.com on Wed Apr 13 20:04:48 1988
  13. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  14. if test -f 'curses.c' -a "${1}" != "-c" ; then 
  15.   echo shar: Will not clobber existing file \"'curses.c'\"
  16. else
  17. echo shar: Extracting \"'curses.c'\" \(20603 characters\)
  18. sed "s/^X//" >'curses.c' <<'END_OF_FILE'
  19. X/* @(#)curses.c    (c) copyright 3/18/87 (Dan Heller) */
  20. X
  21. X/* curses.c -- routine to deal with the curses interface */
  22. X#ifdef CURSES
  23. X
  24. X#include "mush.h"
  25. X#include "bindings.h"
  26. X
  27. curses_init(argc, argv)
  28. register char **argv;
  29. X{
  30. X    char buf[80];
  31. X    extern char *UP, ttytype[];
  32. X
  33. X    if (argv && *++argv && !strcmp(*argv, "-?"))
  34. X    return help(0, "curses", cmd_help);
  35. X    if (iscurses) {
  36. X    print("You can't run curses from the curses mode (silly).");
  37. X    return -1;
  38. X    }
  39. X    if (ison(glob_flags, IS_GETTING)) {
  40. X    print("Finish your letter first.\n");
  41. X    return -1;
  42. X    }
  43. X#ifdef SUNTOOL
  44. X    if (istool) {
  45. X    print("My, aren't we the adventuresome type!");
  46. X    timerclear(&(mail_timer.it_interval));
  47. X    timerclear(&(mail_timer.it_value));
  48. X    tool_destroy(tool), istool = FALSE;
  49. X    curses_init(0, 0);
  50. X    do_loop(); /* doesn't return */
  51. X    }
  52. X#endif /* SUNTOOL */
  53. X
  54. X#ifndef attrset        /* terminfo version of curses */
  55. X    /* you can not start curses in no echo mode.. must be in normal mode */
  56. X    echom();
  57. X    nocrmode();
  58. X#endif /* attrset */
  59. X    (void) initscr();
  60. X#ifdef SIGCONT
  61. X    /* initscr will play with signals -- make sure they're set right. */
  62. X    (void) signal(SIGTSTP, stop_start);
  63. X    (void) signal(SIGCONT, stop_start);
  64. X#endif /* SIGCONT */
  65. X#if !defined(SYSV) && !defined(USG)
  66. X    if (!UP || !*UP)
  67. X#else /* ~SYSV && ~USG */
  68. X    if (!stdscr)
  69. X#endif /* ~SYSV && ~USG */
  70. X         {
  71. X    print("Terminal type %s can not use the curses interface.\n", ttytype);
  72. X    return -1;
  73. X    }
  74. X    iscurses = TRUE;
  75. X    noechom(); /* reset tty state -- */
  76. X    crmode(); /* do not use "echo_on/off()" */
  77. X    scrollok(stdscr, TRUE);
  78. X    /* if the user hasn't set his screen explicitely, set it for him */
  79. X    if (!do_set(set_options, "screen"))
  80. X#ifdef USG
  81. X    switch (_tty.sg_ospeed & CBAUD)
  82. X#else /* USG */
  83. X    switch (_tty.sg_ospeed)
  84. X#endif /* USG */
  85. X    {
  86. X        case B300 :  screen = min(LINES-2, 7);
  87. X        when B1200 : screen = min(LINES-2, 14);
  88. X        when B2400 : screen = min(LINES-2, 22);
  89. X        otherwise :  screen = LINES-2;
  90. X    }
  91. X    else
  92. X    screen = min(screen, LINES-2);
  93. X    crt = LINES;
  94. X    (void) cmd_line(sprintf(buf, "set screen = %d crt = %d", screen, crt),
  95. X    msg_list);
  96. X    if (argc)
  97. X    (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list);
  98. X    if (!do_set(set_options, "no_reverse"))
  99. X    turnon(glob_flags, REV_VIDEO);
  100. X    turnoff(glob_flags, CONT_PRNT);
  101. X    return -1; /* doesn't affect messages */
  102. X}
  103. X
  104. X/*
  105. X * get input in cbreak mode and execute the appropriate command.
  106. X * when the command is done (usually), the user is prompted to
  107. X * hit any key to continue. At this point, the user may enter a
  108. X * new command so no screen refreshing needds to be done. This
  109. X * new command is returned to caller and may be passed back.
  110. X *
  111. X * The flag CNTD_CMD (continued command) is set if
  112. X * this routine is called with the passed parameter (c) > 0. If
  113. X * so, then the character passed is the character input by the
  114. X * user at the last "hit return" prompt indicating that he wants
  115. X * to execute a new command and not draw the screen.
  116. X *
  117. X * CNTD_CMD is also set if the command that the user invokes
  118. X * causes any sort of output that requires a screen refresh.  The
  119. X * variable redo is set to 1 if the header page not only requires
  120. X * redrawing, but updating ... (new call to do_hdrs)
  121. X *
  122. X * calls that say: print("%s", compose_hdr(current_msg)) are constructed
  123. X * that way cuz if the header has a `%' in it, then print will try to
  124. X * expand it.
  125. X */
  126. curses_command(c)
  127. register int c;
  128. X{
  129. X    char     buf[BUFSIZ], file[128], list[128];
  130. X    int     n, curlin;
  131. X    static int  redo;  /* set if headers should be redrawn */
  132. X
  133. X    if (c > 0)
  134. X    turnon(glob_flags, CNTD_CMD);
  135. X    else
  136. X    turnoff(glob_flags, CNTD_CMD);
  137. X    clear_msg_list(msg_list); /* play it safe */
  138. X    if (isoff(glob_flags, CNTD_CMD)) {
  139. X    (void) check_new_mail();
  140. X    curlin = max(1, current_msg - n_array[0] + 1);
  141. X    (void) strncpy(buf, stdscr->_y[curlin], COLS-1);
  142. X    buf[COLS-1] = 0; /* strncpy does not null terminate */
  143. X    if (ison(glob_flags, REV_VIDEO) && msg_cnt)
  144. X        STANDOUT(curlin, 0, buf);
  145. X    mail_status(0);
  146. X    move(curlin, 0), refresh();
  147. X    /* reprint to remove reverse video from current line (don't refresh) */
  148. X    if (ison(glob_flags, REV_VIDEO))
  149. X        mvaddstr(curlin, 0, buf);
  150. X    c = getcmd(); /* get input AFTER line redrawn without reverse video */
  151. X    }
  152. X    buf[0] = list[0] = file[0] = '\0';
  153. X
  154. X    /* goto a specific line number */
  155. X    if (c == C_GOTO_MSG) {
  156. X    c = C_NULL;
  157. X    if (msg_cnt <= 1)
  158. X        print("Not enough messages."), getchar(); /* flush digit typed */
  159. X    else if (curses_msg_list(strcpy(buf, "goto msg: "), list, msg_list)) {
  160. X        n = current_msg;
  161. X        do if (++n >= msg_cnt)
  162. X        n = 0;
  163. X        while (n != current_msg && !msg_bit(msg_list, n));
  164. X        if (n == current_msg && !msg_bit(msg_list, n))
  165. X        print("Message not found.");
  166. X        else if ((current_msg = n) < n_array[0] || n > n_array[screen-1])
  167. X        redo = 1;
  168. X    }
  169. X    if (ison(glob_flags, CNTD_CMD) && msg_cnt)
  170. X        print("%-.*s", COLS-2, compose_hdr(current_msg));
  171. X    if (ison(glob_flags, CNTD_CMD))
  172. X        putchar('\n');
  173. X    } else if (c == C_WRITE_LIST || c == C_SAVE_LIST || c == C_COPY_LIST
  174. X                   || c == C_DELETE_LIST || c == C_UNDEL_LIST) {
  175. X    
  176. X    if (msg_cnt <= 1)
  177. X        print("Not enough messages."), c = C_NULL;
  178. X    else if (ison(glob_flags, READ_ONLY))
  179. X        print("Folder is read-only."), c = C_NULL;
  180. X    else if (!curses_msg_list(sprintf(buf, "%s msg list: ",
  181. X        (c == C_WRITE_LIST)? "write" : (c == C_SAVE_LIST)?  "save" :
  182. X        (c == C_DELETE_LIST)? "delete" : "undelete"), list, msg_list))
  183. X        c = C_NULL;
  184. X    if (ison(glob_flags, CNTD_CMD))
  185. X        putchar('\n');
  186. X    }
  187. X
  188. X    /* first do non-mail command stype stuff */
  189. X    switch (c) {
  190. X    case C_NULL : ;
  191. X
  192. X    /* screen optimization stuff */
  193. X    when C_REVERSE :
  194. X        if (ison(glob_flags, REV_VIDEO))
  195. X        turnoff(glob_flags, REV_VIDEO);
  196. X        else
  197. X        turnon(glob_flags, REV_VIDEO);
  198. X
  199. X    when C_REDRAW : if (!redo) redraw();
  200. X
  201. X    /*
  202. X     * screen movement
  203. X     */
  204. X    when C_NEXT_MSG :
  205. X    /* case 'j' : case 'J' : case '+' : case '\n' : /* next */
  206. X        if (current_msg + 2 > msg_cnt ||
  207. X        isoff(glob_flags, CNTD_CMD) && curlin == screen)
  208. X        bell(); /* reached the end */
  209. X        else {
  210. X        if (++current_msg > n_array[screen-1])
  211. X            redo = 1;
  212. X        if (ison(glob_flags, CNTD_CMD)) {
  213. X            print("%-.*s", COLS-2, compose_hdr(current_msg));
  214. X            putchar('\n');
  215. X        }
  216. X        }
  217. X
  218. X    when C_PREV_MSG :
  219. X    /* when 'k' : case 'K' : case '-' : case CTRL(k) : /* previous */
  220. X        if (isoff(glob_flags, CNTD_CMD) && curlin == 1 || current_msg == 0)
  221. X        bell();  /* at the beginning */
  222. X        else {
  223. X        if (--current_msg < n_array[0])
  224. X            redo = 1;
  225. X        if (ison(glob_flags, CNTD_CMD)) {
  226. X            print("%-.*s", COLS-2, compose_hdr(current_msg));
  227. X            putchar('\n');
  228. X        }
  229. X        }
  230. X
  231. X    when C_FIRST_MSG : case C_LAST_MSG :
  232. X        n = current_msg;
  233. X        move(LINES-1, 0), refresh();
  234. X        if (c == C_FIRST_MSG && (current_msg = 0) < n_array[0] ||
  235. X        c == C_LAST_MSG && (current_msg = msg_cnt-1)> n_array[screen-1])
  236. X        if (isoff(glob_flags, CNTD_CMD))
  237. X            (void) cmd_line(sprintf(buf, "headers %d", current_msg+1),
  238. X                 msg_list);
  239. X        else
  240. X            redo = 1;
  241. X        if (ison(glob_flags, CNTD_CMD) && n != current_msg)
  242. X        print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
  243. X
  244. X    /* top and bottom of headers screen */
  245. X    when C_TOP_PAGE : case C_BOTTOM_PAGE :
  246. X        if (isoff(glob_flags, CNTD_CMD))
  247. X        if (c == C_TOP_PAGE)
  248. X            current_msg = n_array[0];
  249. X        else
  250. X            current_msg = min(n_array[screen-1], msg_cnt-1);
  251. X        else
  252. X        bell();
  253. X
  254. X    when C_NEXT_SCREEN : /* next page */
  255. X        move(LINES-1, 0), refresh();
  256. X        if (msg_cnt > screen) {
  257. X        clear();
  258. X        (void) cmd_line(strcpy(buf, "headers +"), msg_list);
  259. X        current_msg = n_array[0];
  260. X        return redo = 0;
  261. X        } else
  262. X        bell();
  263. X
  264. X    when C_PREV_SCREEN : /* previous page */
  265. X        move(LINES-1, 0), refresh();
  266. X        if (n_array[0] > 0) {
  267. X        clear();
  268. X        (void) cmd_line(strcpy(buf, "headers -"), msg_list);
  269. X        current_msg = n_array[0];
  270. X        return redo = 0;
  271. X        } else
  272. X        bell();
  273. X
  274. X    when C_SHOW_HDR :
  275. X        if (ison(glob_flags, CNTD_CMD) && msg_cnt)
  276. X        puts(compose_hdr(current_msg));
  277. X
  278. X    /* read from/save to record file (.mushrc) */
  279. X    when C_SOURCE : case C_SAVEOPTS : {
  280. X        int argc;
  281. X        char *argv[3];
  282. X        print("%s filename [default]: ",
  283. X        (c == C_SOURCE)? "source" : "save options to");
  284. X        argc = Getstr(file, LINES-40, 0);
  285. X        clr_bot_line();
  286. X        if (argc < 0)
  287. X        return 0;
  288. X        if (argc > 0)
  289. X        argv[1] = file, argc = 2;
  290. X        else
  291. X        argc = 1;
  292. X        argv[argc] = NULL;
  293. X        turnon(glob_flags, PRE_CURSES);
  294. X        if (c == C_SOURCE)
  295. X        (void) source(argc, argv);
  296. X        else
  297. X        (void) save_opts(argc, argv);
  298. X        turnoff(glob_flags, PRE_CURSES);
  299. X    }
  300. X
  301. X    /*
  302. X     * search commands
  303. X     */
  304. X    when C_NEXT_SEARCH : case C_PREV_SEARCH : case C_CONT_SEARCH :
  305. X        if (c != C_CONT_SEARCH)
  306. X        c = search(0 + (c == C_PREV_SEARCH));
  307. X        else
  308. X        c = search(-1);
  309. X        if (ison(glob_flags, CNTD_CMD))
  310. X        putchar('\n');
  311. X        if (c == 0)
  312. X        break;
  313. X        if (ison(glob_flags, CNTD_CMD))
  314. X        print("%-.*s",COLS-2, compose_hdr(current_msg)), putchar('\n');
  315. X        if (n_array[0] > current_msg || n_array[screen-1] < current_msg) {
  316. X        redo = 1;
  317. X        if (isoff(glob_flags, CNTD_CMD))
  318. X            (void) cmd_line(sprintf(buf, "headers %d",
  319. X                        current_msg+1), msg_list);
  320. X        }
  321. X
  322. X    /*
  323. X     * actions on messages
  324. X     */
  325. X    /* delete/undelete */
  326. X    when C_DELETE_MSG : case C_DELETE_LIST :
  327. X    case C_UNDEL_MSG : case C_UNDEL_LIST :
  328. X        if (!msg_cnt) {
  329. X        print("No messages.");
  330. X        if (ison(glob_flags, CNTD_CMD))
  331. X            putchar('\n');
  332. X        break;
  333. X        }
  334. X        if (ison(glob_flags, READ_ONLY)) {
  335. X        print("Folder is read-only.");
  336. X        if (ison(glob_flags, CNTD_CMD))
  337. X            putchar('\n');
  338. X        break;
  339. X        }
  340. X        if (!*list)
  341. X        set_msg_bit(msg_list, current_msg);
  342. X        turnon(glob_flags, DO_UPDATE);
  343. X        for (n = 0; n < msg_cnt; n++)
  344. X        if (msg_bit(msg_list, n)) {
  345. X            if (c == C_DELETE_MSG || c == C_DELETE_LIST)
  346. X            turnon(msg[n].m_flags, DELETE);
  347. X            else
  348. X            turnoff(msg[n].m_flags, DELETE);
  349. X            if (isoff(glob_flags, CNTD_CMD) && (msg_cnt < screen ||
  350. X            n >= n_array[0] && n <= n_array[screen-1]))
  351. X            mvprintw(max(1, n - n_array[0] + 1), 0,
  352. X                "%-.*s", COLS-1, compose_hdr(n));
  353. X            else
  354. X            redo = 1;
  355. X        }
  356. X        if (ison(glob_flags, CNTD_CMD) || *list) {
  357. X        /* print(), THEN putchar() -- overwrite line */
  358. X        if (ison(glob_flags, CNTD_CMD)) {
  359. X            print("%sdeleted %s",
  360. X            (c == C_DELETE_MSG || c == C_DELETE_LIST)? "":"un", list);
  361. X            putchar('\n');
  362. X        }
  363. X        if (ison(msg[current_msg].m_flags, DELETE))
  364. X            (void) next_msg();
  365. X        if (isoff(msg[current_msg].m_flags, DELETE) &&
  366. X            do_set(set_options, "autoprint"))
  367. X            return C_DISPLAY_MSG;
  368. X        if (ison(glob_flags, CNTD_CMD))
  369. X            puts(compose_hdr(current_msg));
  370. X        }
  371. X
  372. X    /*
  373. X     * write/save messages.  If a list is necessary, the user already
  374. X     * entered it above since he must have used a capital letter. If so,
  375. X     * list will contain good data (already been validated above).
  376. X     * if a list is given, set iscurses to 0 so that print statements
  377. X     * will scroll and the user sees the multiple output. else, one
  378. X     * line can go on the bottom line just fine.
  379. X     */
  380. X    when C_WRITE_MSG : case C_SAVE_MSG : case C_COPY_MSG :
  381. X    case C_WRITE_LIST : case C_SAVE_LIST : case C_COPY_LIST : {
  382. X        register char *p =
  383. X        (c == C_WRITE_MSG || c == C_WRITE_LIST)? "write" :
  384. X        (c == C_SAVE_MSG  || c == C_SAVE_LIST)? "save" : "copy";
  385. X        if (!msg_cnt) {
  386. X        print("No messages.");
  387. X        if (ison(glob_flags, CNTD_CMD))
  388. X            putchar('\n');
  389. X        break;
  390. X        }
  391. X        print(sprintf(buf, "filename to %s%s: ", p,
  392. X        (c != C_WRITE_MSG && c != C_WRITE_LIST)? " [mbox]" : ""));
  393. X        if (Getstr(file, COLS-1-strlen(buf), 0) >= 0) {
  394. X        char *argv[3];
  395. X        clr_bot_line();
  396. X        argv[0] = strcpy(buf, p);
  397. X        argv[1] = (*file) ? file : NULL;
  398. X        argv[2] = NULL;
  399. X        if (!*list)
  400. X            set_msg_bit(msg_list, current_msg);
  401. X        move(LINES-1, 0), refresh();
  402. X        if (*list)
  403. X            iscurses = FALSE;
  404. X        /* Turn on piping to make save_msg look at msg_list */
  405. X        turnon(glob_flags, IS_PIPE);
  406. X        if (save_msg(1 + (*file != '\0'), argv, msg_list) < 0)
  407. X            *list = 0;
  408. X        turnoff(glob_flags, IS_PIPE);
  409. X        if (ison(glob_flags, CNTD_CMD))
  410. X            redo = 1, putchar('\n'), puts(compose_hdr(current_msg));
  411. X        if (*list)
  412. X            iscurses = redo = TRUE, turnon(glob_flags, CNTD_CMD);
  413. X        else if (isoff(glob_flags, CNTD_CMD) && msg_cnt)
  414. X            mvprintw(curlin, 0, "%-.*s",
  415. X            COLS-1, compose_hdr(current_msg));
  416. X        } else {
  417. X        print("No messages saved.");
  418. X        if (ison(glob_flags, CNTD_CMD))
  419. X            putchar('\n');
  420. X        }
  421. X    }
  422. X
  423. X    /* preserve message */
  424. X    when C_PRESERVE :
  425. X        if (!msg_cnt) {
  426. X        print("No messages.");
  427. X        if (ison(glob_flags, CNTD_CMD))
  428. X            putchar('\n');
  429. X        break;
  430. X        }
  431. X        if (ison(msg[current_msg].m_flags, PRESERVE))
  432. X        turnoff(msg[current_msg].m_flags, PRESERVE);
  433. X        else
  434. X        turnon(msg[current_msg].m_flags, PRESERVE);
  435. X        turnon(glob_flags, DO_UPDATE);
  436. X        if (ison(glob_flags, CNTD_CMD)) {
  437. X        wprint("%-.*s\n", COLS-1, compose_hdr(current_msg));
  438. X        redo = 1;
  439. X        } else
  440. X        mvprintw(curlin, 0, "%-.*s", COLS-1, compose_hdr(current_msg));
  441. X
  442. X    /* order messages (sort) and rediesplay the headers */
  443. X    when C_SORT : case C_REV_SORT :
  444. X        (void) strcpy(file, "sort");
  445. X        if (c == C_REV_SORT) {
  446. X        print("Reverse "), turnon(glob_flags, CONT_PRNT);
  447. X        (void) strcat(file, " -");
  448. X        }
  449. X        print("Order messages by [Status, date, subject, author]: ");
  450. X        if ((c = getchar()) == 's' || c == 'S' || c == 'd' || c == 'a') {
  451. X        print("reordering messages...");
  452. X        (void) cmd_line(sprintf(buf, "%s %c", file, c), msg_list);
  453. X        print_more("done.");
  454. X        if (ison(glob_flags, CNTD_CMD))
  455. X            putchar('\n'), puts(compose_hdr(current_msg));
  456. X        redo = 1;
  457. X        } else
  458. X        clr_bot_line();
  459. X
  460. X    when C_QUIT_HARD :
  461. X        (void) quit(0, DUBL_NULL);
  462. X        redo = 1; /* new mail must have come in */
  463. X
  464. X    /* quit or update -- vrfy_update (returns 1 if updated) */
  465. X    when C_QUIT : case C_UPDATE : {
  466. X        u_long do_update = ison(glob_flags, DO_UPDATE);
  467. X        clr_bot_line();
  468. X        if (!vrfy_update(&redo))
  469. X        if (c == C_UPDATE)
  470. X            break;
  471. X        else
  472. X            turnoff(glob_flags, DO_UPDATE);
  473. X        if (c == C_QUIT) {
  474. X        if (do_update)
  475. X            putchar('\n');
  476. X        cleanup(0);
  477. X        redo = 1;
  478. X        } else if (isoff(glob_flags, CNTD_CMD))
  479. X        (void) cmd_line(sprintf(buf, "headers %d", current_msg+1),
  480. X                msg_list);
  481. X    }
  482. X
  483. X    when C_EXIT : case C_EXIT_HARD :
  484. X        clr_bot_line();
  485. X        iscurses = FALSE;
  486. X        if (c != C_EXIT && c != C_EXIT_HARD)
  487. X        putchar('\n');
  488. X        cleanup(0);
  489. X
  490. X    /* change to a new folder */
  491. X    when C_FOLDER :
  492. X        for (;;) {
  493. X        int (*oldint)(), (*oldquit)();
  494. X        on_intr();
  495. X        print("New folder (?=list): ");
  496. X        c = Getstr(file, COLS-22, 0);
  497. X        off_intr();
  498. X        if (c > 0) {
  499. X            if (!strcmp(file, "?")) {
  500. X            clr_bot_line();
  501. X            iscurses = 0;
  502. X            puts("folders in your folder directory:");
  503. X            (void) cmd_line(strcpy(buf, "folders"), msg_list);
  504. X    puts("Precede folder names with a +. `%' to specify system mailbox.");
  505. X            turnon(glob_flags, CNTD_CMD), iscurses = 1;
  506. X            continue;
  507. X            }
  508. X            clearok(stdscr, FALSE);
  509. X            /* if vrfy_update doesn't verify, but folder command fails,
  510. X             * then we need to reset the updatability of curren folder
  511. X             */
  512. X            c = (ison(glob_flags, DO_UPDATE))? TRUE : FALSE;
  513. X            if (strcmp(file, "-?"))
  514. X            (void) vrfy_update(&redo);
  515. X            move(LINES-1, 0), refresh();
  516. X            if (cmd_line(sprintf(buf, "folder ! -N %s", file),
  517. X                 msg_list) == -1) {
  518. X            if (c) /* remember state of updatability of folder */
  519. X                turnon(glob_flags, DO_UPDATE);
  520. X            if (ison(glob_flags, CNTD_CMD))
  521. X                putchar('\n');
  522. X            } else
  523. X            redo = 1, turnoff(glob_flags, CNTD_CMD);
  524. X            break;
  525. X        } else {
  526. X            print("\"%s\" unchanged.", mailfile);
  527. X            if (ison(glob_flags, CNTD_CMD))
  528. X            putchar('\n');
  529. X            break;
  530. X        }
  531. X        }
  532. X
  533. X    /* shell escape */
  534. X    when C_SHELL_ESC :
  535. X        print("Shell command: ");
  536. X        if (Getstr(file, COLS-24, 0) < 0)
  537. X        clr_bot_line();
  538. X        else {
  539. X        putchar('\n');
  540. X        iscurses = FALSE;
  541. X        (void) cmd_line(sprintf(buf, "sh %s", file), msg_list);
  542. X        iscurses = TRUE;
  543. X        turnon(glob_flags, CNTD_CMD);
  544. X        }
  545. X
  546. X    /* do a line-mode like command */
  547. X    when C_CURSES_ESC :
  548. X        print(":");
  549. X        if (Getstr(buf, COLS-2, 0) < 0)
  550. X        break;
  551. X        putchar('\n');
  552. X        iscurses = FALSE;
  553. X        if (!*buf) {
  554. X        /* return -1 because iscurses = 0 is not enough! */
  555. X        redo = 0;
  556. X        endwin(); /* this turns echoing back on! */
  557. X        echo_off();
  558. X        return -1;
  559. X        }
  560. X        (void) cmd_line(buf, msg_list);
  561. X        /* they may have affected message status or had text output */
  562. X        turnon(glob_flags, CNTD_CMD), redo = 1;
  563. X        iscurses = TRUE;
  564. X        if (msg_cnt)
  565. X        puts(compose_hdr(current_msg));
  566. X
  567. X    /* send message to printer */
  568. X    when C_PRINT_MSG : (void) lpr(0, DUBL_NULL, msg_list);
  569. X
  570. X    /* cd */
  571. X    when C_CHDIR :
  572. X        print("chdir to [.]: ");
  573. X        if (Getstr(file, COLS-12, 0) < 0)
  574. X        break;
  575. X        clr_bot_line();
  576. X        (void) cmd_line(sprintf(buf, "cd %s", file), msg_list);
  577. X        if (ison(glob_flags, CNTD_CMD))
  578. X        putchar('\n');
  579. X
  580. X    /* variable settings */
  581. X    when C_VAR_SET : case C_IGNORE : case C_ALIAS : case C_OWN_HDR :
  582. X        curs_vars(c); /* CNTD_CMD is reset if there's output! */
  583. X
  584. X    when C_VERSION :
  585. X        (void) do_version();
  586. X        if (ison(glob_flags, CNTD_CMD))
  587. X        putchar('\n');
  588. X
  589. X    when C_MAIL_FLAGS :
  590. X        print("flags [-?]: ");
  591. X        if ((c = Getstr(file, COLS-12, 0)) < 0)
  592. X        break;
  593. X        putchar('\n');
  594. X        if (c == 0)
  595. X        (void) strcpy(file, "-?");
  596. X    /* Fall thru */
  597. X    case C_MAIL : {
  598. X        u_long flgs = glob_flags;
  599. X        turnon(glob_flags, IGN_BANG);
  600. X        clr_bot_line();
  601. X        iscurses = FALSE;
  602. X        (void) cmd_line(sprintf(buf, "mail %s", file), msg_list);
  603. X        glob_flags = flgs;
  604. X        iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
  605. X        if (msg_cnt)
  606. X        print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
  607. X    }
  608. X
  609. X    /* reply to mail */
  610. X    when C_REPLY_SENDER : case C_REPLY_ALL : {
  611. X        register char *p = (c == C_REPLY_ALL)? "replyall" : "replysender";
  612. X        clr_bot_line();
  613. X        iscurses = FALSE;
  614. X        if (isoff(msg[current_msg].m_flags, REPLIED))
  615. X        redo = 1;
  616. X        (void) cmd_line(sprintf(buf, "%s %d", p, current_msg+1),
  617. X        msg_list);
  618. X        if (msg_cnt)
  619. X        puts(compose_hdr(current_msg));
  620. X        iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
  621. X    }
  622. X
  623. X    /* type out a message */
  624. X    when C_DISPLAY_MSG : case C_TOP_MSG : case C_DISPLAY_NEXT :
  625. X        if (!msg_cnt ||
  626. X        c != C_DISPLAY_NEXT && ison(msg[current_msg].m_flags, DELETE)) {
  627. X        if (!msg_cnt)
  628. X            print("No messages.");
  629. X        else
  630. X            print("Message %d deleted; type 'u' to undelete.",
  631. X                      current_msg+1);
  632. X        if (ison(glob_flags, CNTD_CMD))
  633. X            putchar('\n');
  634. X        break;
  635. X        }
  636. X        clr_bot_line();
  637. X        iscurses = FALSE;
  638. X        if (ison(glob_flags, CNTD_CMD))
  639. X        putchar('\n');
  640. X        if (c == C_DISPLAY_MSG)
  641. X        c = cmd_line(strcpy(buf, "type"), msg_list);
  642. X        else if (c == C_TOP_MSG)
  643. X        c = cmd_line(strcpy(buf, "top"), msg_list);
  644. X        else
  645. X        c = cmd_line(strcpy(buf, "next"), msg_list);
  646. X        if (c > -1)
  647. X        turnon(glob_flags, CNTD_CMD), redo = 1;
  648. X        iscurses = TRUE;
  649. X        puts(compose_hdr(current_msg));
  650. X
  651. X    /* bind a key or string to a command */
  652. X    when C_BIND :  case C_UNBIND : {
  653. X        char *argv[2];
  654. X        argv[0] = (c == C_BIND) ? "bind" : "unbind";
  655. X        argv[1] = NULL;
  656. X        if (bind_it(0, argv) < -1)
  657. X        turnon(glob_flags, CNTD_CMD);
  658. X        else if (ison(glob_flags, CNTD_CMD)) /* if it was set anyway */
  659. X        putchar('\n');
  660. X    }
  661. X
  662. X    /* help stuff */
  663. X    when C_HELP :
  664. X        (void) c_bind(NULL);
  665. X        turnon(glob_flags, CNTD_CMD);
  666. X        if (msg_cnt)
  667. X        puts(compose_hdr(current_msg));
  668. X
  669. X    /* now do interactive stuff as if run from the mush shell */
  670. X    otherwise :
  671. X        bell();
  672. X        if (ison(glob_flags, CNTD_CMD)) {
  673. X        /* use print instead of puts to overwrite hit_return msg */
  674. X        print("unknown command"), putchar('\n');
  675. X        redo = 1;
  676. X        }
  677. X    }
  678. X
  679. X    if (ison(glob_flags, CNTD_CMD)) {
  680. X    int old_cnt = msg_cnt;
  681. X    if (!(c = hit_return()) && !redo && msg_cnt == old_cnt)
  682. X        redraw();
  683. X    clr_bot_line();
  684. X    if (old_cnt !=  msg_cnt)
  685. X        redo = 1;
  686. X    if (c)
  687. X        return c;
  688. X    }
  689. X    if (redo) {
  690. X    n = current_msg;
  691. X    clear();
  692. X    if (msg_cnt < screen || n_array[0] < n && n < n_array[screen-1])
  693. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  694. X    else
  695. X        (void) cmd_line(sprintf(buf, "headers %d", n+1), msg_list);
  696. X    redo = 0;
  697. X    }
  698. X    return 0;
  699. X}
  700. X
  701. vrfy_update(redo)
  702. int *redo;
  703. X{
  704. X    char buf[16];
  705. X    int c;
  706. X
  707. X    /* update current folder */
  708. X    if (ison(glob_flags, DO_UPDATE)) {
  709. X    if (ison(glob_flags, READ_ONLY)) {
  710. X        print("Folder is read-only.");
  711. X        if (ison(glob_flags, CNTD_CMD))
  712. X        putchar('\n');
  713. X        return 0;
  714. X    }
  715. X    print("Update folder [y]? ");
  716. X    if ((c = getchar()) != 'y' && c != 'Y' && c != '\n' && !isspace(c)) {
  717. X        print("Folder unchanged.");
  718. X        if (ison(glob_flags, CNTD_CMD))
  719. X        putchar('\n');
  720. X        return 0;
  721. X    }
  722. X    if (cmd_line(strcpy(buf, "update"), msg_list) != -1 &&
  723. X        ison(glob_flags, CNTD_CMD))
  724. X        *redo = 1, turnoff(glob_flags, CNTD_CMD);
  725. X    }
  726. X    turnoff(glob_flags, DO_UPDATE);
  727. X    return 1; /* make sure bottom line is clear and no reverse video */
  728. X}
  729. X#endif /* CURSES */
  730. END_OF_FILE
  731. if test 20603 -ne `wc -c <'curses.c'`; then
  732.     echo shar: \"'curses.c'\" unpacked with wrong size!
  733. fi
  734. # end of 'curses.c'
  735. fi
  736. if test -f 'msgs.c' -a "${1}" != "-c" ; then 
  737.   echo shar: Will not clobber existing file \"'msgs.c'\"
  738. else
  739. echo shar: Extracting \"'msgs.c'\" \(19132 characters\)
  740. sed "s/^X//" >'msgs.c' <<'END_OF_FILE'
  741. X/* @(#)msgs.c    (c) copyright 10/18/86 (Dan Heller) */
  742. X
  743. X#include "mush.h"
  744. X#ifdef SYSV
  745. X#ifndef USG
  746. X#include <sys/locking.h>
  747. X#else /* USG */
  748. X#include <unistd.h>
  749. X#endif /* USG */
  750. X#endif /* SYSV */
  751. X
  752. lock_file(filename, fd)
  753. char *filename;
  754. X{
  755. X#ifdef SYSV
  756. X#ifndef USG
  757. X    (void) locking(fd, LK_LOCK, 0); /* xenix */
  758. X#else
  759. X    /* if unable to lock, tell them */
  760. X    if (Access(filename, W_OK) || lockf(fd, F_TLOCK, 0)) /* system-v */
  761. X    return -1;
  762. X#endif /* USG */
  763. X#else
  764. X#ifdef BSD
  765. X    if (flock(fd, LOCK_SH))  /* if exclusively locked, flock blocks */
  766. X    return -1;
  767. X#else /* BSD */
  768. X    "There is no supported file locking function compiled in this version!";
  769. X#endif /* BSD */
  770. X#endif /* SYSV */
  771. X    return 0;
  772. X}
  773. X
  774. close_lock(fp)
  775. FILE *fp;
  776. X{
  777. X#ifdef SYSV
  778. X#ifndef USG
  779. X    locking(fileno(fp), LK_UNLCK, 0);
  780. X#else
  781. X    lockf(fileno(fp), F_ULOCK, 0);
  782. X#endif /* USG */
  783. X#endif /* SYSV */
  784. X    fclose(fp);            /* implicit unlock for BSD */
  785. X}
  786. X
  787. void
  788. display_msg(n, flg)
  789. register int n;
  790. long flg;
  791. X{
  792. X    register FILE *pp;
  793. X
  794. X    if (ison(msg[n].m_flags, DELETE)) {
  795. X    print("Message %d deleted; ", n+1);
  796. X#ifdef SUNTOOL
  797. X    if (istool)
  798. X        print_more("Select UNDELETE to read."), do_clear();
  799. X    else
  800. X#endif /* SUNTOOL */
  801. X    if (iscurses)
  802. X        print_more("Type 'u' to undelete.");
  803. X    else
  804. X        print("Type 'undelete %d' to undelete\n", n+1);
  805. X    return;
  806. X    }
  807. X    set_isread(n);
  808. X    if (ison(flg, TOP)) {
  809. X    turnon(flg, NO_HEADER);
  810. X    print("Top of "), turnon(glob_flags, CONT_PRNT);
  811. X    }
  812. X
  813. X    if (!istool && isoff(flg, NO_PAGE) &&
  814. X        crt < msg[n].m_lines && isoff(flg, TOP)) {
  815. X    char buf[32], *pager = do_set(set_options, "pager");
  816. X    if (!pager)
  817. X        pager = DEF_PAGER;
  818. X    if (!*pager || !strcmp(pager, "internal"))
  819. X        pager = NULL; /* default to internal pager if pager set to "" */
  820. X    (void) do_pager(pager, TRUE); /* start pager */
  821. X    (void) do_pager(sprintf(buf, "Message #%d (%d lines)\n",
  822. X             n+1, msg[n].m_lines), FALSE);
  823. X    (void) copy_msg(n, NULL_FILE, flg);
  824. X    (void) do_pager(NULL, FALSE); /* end pager */
  825. X    } else {
  826. X    print("Message #%d (%d lines)\n", n+1, msg[n].m_lines);
  827. X    (void) copy_msg(n, stdout, flg);
  828. X    }
  829. X}
  830. X
  831. X/*
  832. X * copy message 'n' to file "fp" according to various flag arguments
  833. X * return number of lines copied or -1 if system error on fputs.
  834. X * If "fp" is null, send to internal pager.  This can only happen from
  835. X * display_msg above.
  836. X */
  837. copy_msg(n, fp, flags)
  838. register int n;
  839. long flags;
  840. register FILE *fp;
  841. X{
  842. X    register int  ignoring = 0, lines = 0;
  843. X    register char *indent_str;
  844. X    int  on_hdr = 1, top, squeeze = FALSE;
  845. X    char       line[BUFSIZ], *show_hdrs = NULL;
  846. X
  847. X    still_more = 0;
  848. X    if (ison(flags, TOP)) {
  849. X    register char *p = do_set(set_options, "toplines");
  850. X    top = (p)? atoi(p) : crt;
  851. X    }
  852. X    /* When updating to a folder, always write all headers! */
  853. X    if (ison(flags, UPDATE_STATUS))
  854. X    turnon(flags, NO_IGNORE);
  855. X    else if (do_set(set_options, "alwaysignore"))
  856. X    turnoff(flags, NO_IGNORE);
  857. X    if (isoff(flags, NO_IGNORE)) {
  858. X    if (do_set(set_options, "squeeze"))
  859. X        squeeze = TRUE;
  860. X    show_hdrs = do_set(set_options, "show_hdrs");
  861. X    }
  862. X
  863. X#ifdef SUNTOOL
  864. X    if (istool && (!fp || fp == stdout)) {
  865. X    register int x = (msg[n].m_lines + 2) * l_height(curfont);
  866. X
  867. X    if (x > 32765) { /* to overcome a bug in pixrects that sun won't fix */
  868. X        print("message too big to display using this font");
  869. X        return 0;
  870. X    }
  871. X    if (x < msg_rect.r_height) /* make it at least as big as the window */
  872. X        x = msg_rect.r_height;
  873. X    /* If the window isn't big enough, an inifite loop occurs in Addstr */
  874. X    if (x < 2 * l_height(curfont) || msg_rect.r_width < 3*l_width(curfont))
  875. X        return 0;
  876. X    do_clear();
  877. X    lock_cursors();
  878. X    /* msg_pix is for Addstr() */
  879. X    if (!(msg_pix = mem_create(msg_rect.r_width, x, 1))) {
  880. X        error("mem_create");
  881. X        return 0;
  882. X    }
  883. X    pr_rop(msg_pix, 0,0, msg_rect.r_width-1, x-1, PIX_CLR, 0,0,0);
  884. X    on_hdr = 1;
  885. X    }
  886. X#endif /* SUNTOOL */
  887. X    if (ison(flags, INDENT)) {
  888. X    if ((indent_str = do_set(set_options, "pre_indent_str"))) {
  889. X        char *old_fmt = hdr_format;
  890. X        hdr_format = indent_str;
  891. X        fprintf(fp, "%s\n", compose_hdr(n) + 9); /* magic number 9 !! */
  892. X        hdr_format = old_fmt;
  893. X    }
  894. X    if (!(indent_str = do_set(set_options, "indent_str")))
  895. X        indent_str = DEF_INDENT_STR;
  896. X    }
  897. X    if (fseek(tmpf, msg[n].m_offset, L_SET) == -1) {
  898. X    error("Unable to find msg %d", n+1);
  899. X    return -1;
  900. X    }
  901. X    while (still_more < msg[n].m_size && fgets(line, BUFSIZ, tmpf)) {
  902. X    still_more += strlen(line);
  903. X    /*
  904. X     * If squeeze is one, all blanks lines squeeze down to one blank line.
  905. X     * If squeeze is two, squeezing is in progress so wait for the next \n.
  906. X     */
  907. X    if (*line == '\n') {
  908. X        if (on_hdr)    /* blank line -- end of header */
  909. X        turnoff(flags, NO_HEADER), on_hdr = 0;
  910. X        if (squeeze > 1)
  911. X        continue;
  912. X        else if (squeeze)
  913. X        squeeze = 2;
  914. X    } else if (squeeze > 1)
  915. X        squeeze = 1;
  916. X
  917. X    if (ison(flags, UPDATE_STATUS))
  918. X        if (!strncmp(line, "Status:", 7))
  919. X        continue; /* ignore this and other "Status" lines */
  920. X        else if (!on_hdr) {
  921. X        /* preserve NEW/UNREAD status on preserved messages */
  922. X        register char *p = line;
  923. X        p += Strcpy(p, "Status: O");
  924. X        if (isoff(msg[n].m_flags, UNREAD) &&
  925. X            isoff(msg[n].m_flags, PRESERVE))
  926. X            *p++ = 'R';
  927. X        if (ison(msg[n].m_flags, REPLIED))
  928. X            *p++ = 'r';
  929. X        *p++ = '\n', *p = 0;
  930. X        fputs(line, fp);
  931. X        (void) strcpy(line, "\n");
  932. X        turnoff(flags, UPDATE_STATUS);
  933. X        }
  934. X    if (on_hdr && isoff(flags, NO_IGNORE)) {
  935. X        register char *p = any(line, " \t:");
  936. X        if (!p)
  937. X        ignoring = 0, on_hdr = 0;
  938. X        else if (ignoring)
  939. X        if (*p != ':') {
  940. X            Debug("Ignoring: %s", line);
  941. X            continue;
  942. X        } else
  943. X            ignoring = 0;
  944. X        if (p && *p == ':') {
  945. X        *p = 0;
  946. X        ignoring = 0;
  947. X        if (show_hdrs) {
  948. X            if (!chk_two_lists(line, show_hdrs, ":, \t"))
  949. X            ignoring = 1;
  950. X        } else {
  951. X            register struct options *opts;
  952. X            for (opts = ignore_hdr; opts; opts = opts->next)
  953. X            if (!lcase_strcmp(opts->option, line)) {
  954. X                ignoring = 1;
  955. X                break;
  956. X            }
  957. X        }
  958. X        *p = ':';
  959. X        if (ignoring) {
  960. X            Debug("Ignoring: %s", line);
  961. X            continue;
  962. X        }
  963. X        }
  964. X    }
  965. X    if (!on_hdr && ison(flags, TOP) && !--top)
  966. X        break;
  967. X    if (isoff(flags, NO_HEADER)) {
  968. X        /* note that function returns the number of lines */
  969. X        lines++;
  970. X#ifdef SUNTOOL
  971. X        if (istool && (!fp || fp == stdout)) {
  972. X        Addstr(line);
  973. X        continue;
  974. X        }
  975. X#endif /* SUNTOOL */
  976. X        if (ison(flags, INDENT))
  977. X        fputs(indent_str, fp);
  978. X        if (!fp) {
  979. X        if (do_pager(line, FALSE) == EOF)
  980. X            return -1;
  981. X        } else if (fputs(line, fp) == EOF)
  982. X        /* Pipe broken, out of filespace, etc */
  983. X        return -1;
  984. X    }
  985. X    }
  986. X    if (ison(flags, INDENT) &&
  987. X    (indent_str = do_set(set_options, "post_indent_str")) && *indent_str) {
  988. X    char *old_fmt = hdr_format;
  989. X    hdr_format = indent_str;
  990. X    fprintf(fp, "%s\n", compose_hdr(n)+9); /* magic number 9 !! */
  991. X    hdr_format = old_fmt;
  992. X    }
  993. X#ifdef SUNTOOL
  994. X    if (istool && (!fp || fp == stdout)) {
  995. X    unlock_cursors();
  996. X    txt.y = still_more = msg_rect.r_height;
  997. X    scroll_win(0);  /* causes a display */
  998. X    }
  999. X#endif /* SUNTOOL */
  1000. X    return lines;
  1001. X}
  1002. X
  1003. X/* get mail from whatever the mailfile points to. open a tempfile for
  1004. X * appending, then close it and reopen it for read-only.  some systems
  1005. X * have flakey read/write access.
  1006. X */
  1007. void
  1008. getmail()
  1009. X{
  1010. X    register FILE    *mail_fp;
  1011. X    int     lines = 0, get_status = 1, len;
  1012. X    long     ftell(), bytes;
  1013. X    char    line[BUFSIZ];
  1014. X
  1015. X#ifdef SYSV
  1016. X    /* for SVID systems to lock, the file must be open for read/write */
  1017. X    if (isoff(glob_flags, READ_ONLY))
  1018. X    mail_fp = fopen(mailfile, "r+");
  1019. X    else
  1020. X#endif /* SYSV */
  1021. X    mail_fp = fopen(mailfile, "r");
  1022. X
  1023. X    if (!mail_fp) {
  1024. X    error("Unable to open %s", mailfile);
  1025. X    return;
  1026. X    }
  1027. X    /*
  1028. X     * since this file is usually open for read-only, close it and then
  1029. X     * reopen it for appending.  This is done to compensate for errors
  1030. X     * in XENIX and to play it safe with non-essentially writable files.
  1031. X     * see more notes below (end of proc).
  1032. X     */
  1033. X    if (isoff(glob_flags, READ_ONLY)) {
  1034. X    int    omask = umask(077);
  1035. X
  1036. X    (void) fclose(tmpf);
  1037. X    tmpf = fopen(tempfile, "a");
  1038. X    (void) umask(omask);
  1039. X    if (!tmpf) {
  1040. X        error("Unable to open %s for appending", tempfile);
  1041. X        (void) fclose(mail_fp);
  1042. X        return;
  1043. X    }
  1044. X    } else if (msg_cnt)
  1045. X    (void) fseek(tmpf, msg[msg_cnt-1].m_offset+msg[msg_cnt-1].m_size,L_SET);
  1046. X
  1047. X    if (isoff(glob_flags, READ_ONLY) && lock_file(mailfile, fileno(mail_fp)))
  1048. X    error("WARNING: unable to lock %s", mailfile);
  1049. X
  1050. X    (void) fseek(mail_fp, ftell(tmpf), L_SET);
  1051. X
  1052. X#ifdef MSG_SEPARATOR
  1053. X    len = strlen(MSG_SEPARATOR);
  1054. X#endif /* MSG_SEPARATOR */
  1055. X
  1056. X    while (fgets(line, BUFSIZ, mail_fp) != NULL) {
  1057. X#ifndef MSG_SEPARATOR
  1058. X    if (!strncmp(line, "From ", 5) &&
  1059. X        !sscanf(line+5, "%*s %*s %*s %*d %*d:%*d"))
  1060. X#else /* MSG_SEPARATOR */
  1061. X    if (!strncmp(line, MSG_SEPARATOR, len))
  1062. X#endif /* MSG_SEPARATOR */
  1063. X    {
  1064. X        if (msg_cnt == MAXMSGS-1) {
  1065. X        print("WARNING: exceeded %d messages.\n", MAXMSGS);
  1066. X        print("You should split \"%s\" into smaller files.\n",mailfile);
  1067. X        /* make sure that tempfile isn't removed!! */
  1068. X        turnon(glob_flags, IGN_SIGS);
  1069. X        cleanup(0); /* probably a more elegant way to exit, but... */
  1070. X        }
  1071. X        bytes = ftell(tmpf);
  1072. X        /* finish up message structure from previous message.
  1073. X         * if this is incorporating new mail, check "lines" to
  1074. X         * see if previous message has already been set!
  1075. X         */
  1076. X        if (msg_cnt && lines) {
  1077. X        msg[msg_cnt-1].m_size = bytes - msg[msg_cnt-1].m_offset;
  1078. X        msg[msg_cnt-1].m_lines = lines;
  1079. X        }
  1080. X        msg[msg_cnt].m_offset = bytes;
  1081. X        msg[msg_cnt].m_flags = lines = 0;
  1082. X        turnon(msg[msg_cnt].m_flags, UNREAD); /* initialize */
  1083. X
  1084. X        if (isoff(glob_flags, READ_ONLY)) {
  1085. X        fputs(line, tmpf);
  1086. X        if (errno == ENOSPC)
  1087. X            fs_error();
  1088. X        }
  1089. X        /* we've read the "From " line, now read the rest of
  1090. X         * the message headers till we get to a blank line.
  1091. X         */
  1092. X        while (fgets(line, BUFSIZ, mail_fp) && (*line != '\n')) {
  1093. X        register char *p = line;
  1094. X        if (get_status && !(get_status = strncmp(p, "Status:", 7))) {
  1095. X            turnon(msg[msg_cnt].m_flags, OLD);
  1096. X            for (p += 8 ; *p != '\n'; p++)
  1097. X            switch(*p) {
  1098. X                when 'R': turnoff(msg[msg_cnt].m_flags, UNREAD);
  1099. X                when 'P': turnon(msg[msg_cnt].m_flags, UNREAD);
  1100. X                when 'r': turnon(msg[msg_cnt].m_flags, REPLIED);
  1101. X                otherwise :
  1102. X                if (ison(glob_flags, WARNING))
  1103. X                    print("unknown msg status flag: %c", *p);
  1104. X            }
  1105. X        }
  1106. X        lines++;
  1107. X        if (isoff(glob_flags, READ_ONLY)) {
  1108. X            fputs(line, tmpf);
  1109. X            if (errno == ENOSPC)
  1110. X            fs_error();
  1111. X        }
  1112. X        }
  1113. X        msg_cnt++, get_status = 1;
  1114. X    }
  1115. X    lines++;
  1116. X    if (isoff(glob_flags, READ_ONLY)) {
  1117. X        fputs(line, tmpf);
  1118. X        if (errno == ENOSPC)
  1119. X        fs_error();
  1120. X    } else
  1121. X        (void) fseek(tmpf, ftell(mail_fp), L_SET);
  1122. X    }
  1123. X    /* msg_cnt may be 0 if there is an error with the format of mailfile */
  1124. X    if (msg_cnt) {
  1125. X    msg[msg_cnt-1].m_size = ftell(tmpf) - msg[msg_cnt-1].m_offset;
  1126. X    msg[msg_cnt-1].m_lines = lines;
  1127. X    }
  1128. X
  1129. X    close_lock(mail_fp);
  1130. X
  1131. X    /* I've had problems with sys-v opening a file for read/write. I'd
  1132. X     * try fgets after a seek to an arbitrary place and get NULL. "w+"
  1133. X     * could be broken (XENIX), so play it safe anyway.
  1134. X     */
  1135. X    if (isoff(glob_flags, READ_ONLY)) {
  1136. X    fclose(tmpf);
  1137. X    if (!(tmpf = fopen(tempfile, "r")))
  1138. X        error("unable to open %s for reading", tempfile);
  1139. X    }
  1140. X}
  1141. X
  1142. fs_error()
  1143. X{
  1144. X    error("WARNING: unable to write to \"%s\"", tempfile);
  1145. X    print("Read the manual on what to do on full file systems.\n");
  1146. X    cleanup(0);
  1147. X}
  1148. X
  1149. X/*
  1150. X * copy temp or whatever back to mailfile
  1151. X * Return 0 if new mail came and user doesn't want to exit.
  1152. X */
  1153. copyback()
  1154. X{
  1155. X    register int    new = 0, i, j=0, k=0;
  1156. X    register long    flg = 0;
  1157. X    register FILE    *mbox = NULL_FILE, *mail_fp;
  1158. X    char        *mbox_file, action = 0;
  1159. X    int         hold = 0, delete_it = 0, dont_unlink = FALSE;
  1160. X
  1161. X#ifdef SUNTOOL
  1162. X    if (istool) {
  1163. X    timerclear(&(mail_timer.it_interval));
  1164. X    timerclear(&(mail_timer.it_value));
  1165. X    }
  1166. X#endif /* SUNTOOL */
  1167. X    if (ison(glob_flags, READ_ONLY)) {
  1168. X    print("Unable to update %s: read only\n", mailfile);
  1169. X    return 1;
  1170. X    }
  1171. X    if (check_new_mail()) {
  1172. X    new = 1;
  1173. X    if (!istool) {
  1174. X        char buf[256];
  1175. X        if (iscurses)
  1176. X        putchar('\n');
  1177. X        print("Really quit? ");
  1178. X        buf[0] = 0;
  1179. X        if (!Getstr(buf, 256, 0) || lower(*buf) != 'y')
  1180. X        return 0;
  1181. X    }
  1182. X    } else if (!msg_cnt) /* prevent unnecessary overwrite */
  1183. X    return 0;
  1184. X    /* open mbox if: "autodelete" AND "hold" are NOT set. */
  1185. X    if (!strcmp(mailfile, spoolfile)
  1186. X        && !(delete_it = !!do_set(set_options, "autodelete"))
  1187. X        && !(hold = !!do_set(set_options, "hold"))) {
  1188. X    register char *p;
  1189. X    int x = 1; /* tell getpath to ignore "ENOENT" if file not found */
  1190. X
  1191. X    if (!(p = do_set(set_options, "mbox")))
  1192. X        p = DEF_MBOX;
  1193. X    mbox_file = getpath(p, &x);
  1194. X    if (x) {
  1195. X        if (x > 0)
  1196. X        print("%s is a directory.\n", mbox_file);
  1197. X        else
  1198. X        print("Unable to open %s: %s\n", p, mbox_file);
  1199. X        mbox = NULL_FILE;
  1200. X    } else {
  1201. X        if (Access(mbox_file, F_OK) == -1) /* does it exist? */
  1202. X        mbox = fopen(mbox_file, "w");
  1203. X        else
  1204. X        mbox = fopen(mbox_file, "a");
  1205. X        if (!mbox)
  1206. X        error("Unable to write to %s", mbox_file);
  1207. X    }
  1208. X    }
  1209. X    /* reopen the mailfile; set umask accordingly */
  1210. X    {
  1211. X    int omask = umask(077);
  1212. X    mail_fp = fopen(mailfile, "w+");
  1213. X    (void) umask(omask);
  1214. X    if (!mail_fp) {
  1215. X        error("Unable to rewrite %s", mailfile);
  1216. X        return 0;
  1217. X    }
  1218. X    }
  1219. X    turnon(glob_flags, IGN_SIGS);
  1220. X    print("Updating \"%s\"", mailfile);
  1221. X
  1222. X    if (lock_file(mailfile, fileno(mail_fp)))
  1223. X    error("WARNING: unable to lock %s", mailfile);
  1224. X
  1225. X    turnon(flg, UPDATE_STATUS);
  1226. X    turnon(flg, NO_IGNORE);
  1227. X
  1228. X    for (i = 0; i < msg_cnt; i++)
  1229. X    /* check to see if message is marked for deletion or, if read and not
  1230. X     * preserved, delete it if autodelete is set. Otherwise, save the
  1231. X     * message in the spool file if hold is set. If all fails, save in mbox.
  1232. X     */
  1233. X    if (ison(msg[i].m_flags, DELETE)
  1234. X        || isoff(msg[i].m_flags, UNREAD) && isoff(msg[i].m_flags, PRESERVE) 
  1235. X        && delete_it) {
  1236. X        Debug("%s %d",
  1237. X        (action!='d')? "\ndeleting message:" : "", i+1), action = 'd';
  1238. X        continue;
  1239. X    } else if (ison(msg[i].m_flags, UNREAD) ||
  1240. X         ison(msg[i].m_flags, PRESERVE) || hold || !mbox) {
  1241. X        j++;
  1242. X        Debug("%s %d",
  1243. X        (action!='s')? "\nsaving in spool:" : "", i+1), action = 's';
  1244. X        if (copy_msg(i, mail_fp, flg) == -1) {
  1245. X        error("WARNING: unable to write back to spool");
  1246. X        print("ALL mail left in %s\n", tempfile);
  1247. X        print("Spool mailbox may be corrupted.\n");
  1248. X        if (new)
  1249. X            print("New mail may be lost. :-(\n");
  1250. X        dont_unlink = TRUE;
  1251. X        break;
  1252. X        }
  1253. X    } else if (!strcmp(mailfile, spoolfile)) {   /* copy back to mbox */
  1254. X        k++;
  1255. X        if (copy_msg(i, mbox, flg) == -1) {
  1256. X        error("WARNING: unable to write to mbox");
  1257. X        print("Unresolved mail left in %s\n", tempfile);
  1258. X        dont_unlink = TRUE;
  1259. X        break;
  1260. X        }
  1261. X        Debug("%s %d",
  1262. X        (action!='m')? "\nsaving in mbox:" : "", i+1), action = 'm';
  1263. X    }
  1264. X    Debug("\n%s", mailfile);
  1265. X
  1266. X    close_lock(mail_fp);
  1267. X
  1268. X    if (mbox)
  1269. X    fclose(mbox);
  1270. X    if (j) {
  1271. X    long times[2];
  1272. X    times[1] = time(×[0]) - (long)2;
  1273. X    if (!strcmp(mailfile, spoolfile) && utime(mailfile, times))
  1274. X        error("utime");
  1275. X    print_more(": saved %d message%s\n", j, (j==1)? NO_STRING: "s");
  1276. X    } else if (strcmp(mailfile, spoolfile) && !dont_unlink && !new)
  1277. X    if (unlink(mailfile))
  1278. X        turnon(glob_flags, CONT_PRNT), error(": cannot remove");
  1279. X    else
  1280. X        print_more(": removed\n");
  1281. X    else
  1282. X    print_more(": empty\n");
  1283. X    if (k)
  1284. X    print("saved %d message%s in %s\n",k,(k==1)? NO_STRING: "s",mbox_file);
  1285. X    if (new && !istool)
  1286. X    print("New mail has arrived.\n");
  1287. X    turnoff(glob_flags, IGN_SIGS);
  1288. X#ifdef SUNTOOL
  1289. X    if (istool) {
  1290. X    mail_timer.it_value.tv_sec = time_out;
  1291. X    setitimer(ITIMER_REAL, &mail_timer, NULL);
  1292. X    }
  1293. X#endif /* SUNTOOL */
  1294. X    return 1;
  1295. X}
  1296. X
  1297. mail_size()
  1298. X{
  1299. X    struct stat buf;
  1300. X    if (strcmp(mailfile, spoolfile)) {
  1301. X    char tmp[128];
  1302. X    if (!stat(sprintf(tmp, "%s/%s", MAILDIR, login), &buf))
  1303. X        spool_size = buf.st_size;
  1304. X    }
  1305. X    if (!*mailfile)
  1306. X    return 0;
  1307. X    if (stat(mailfile, &buf)) {
  1308. X    if (errno != ENOENT)
  1309. X        error("Unable to stat %s", mailfile);
  1310. X    return 0;
  1311. X    }
  1312. X    if (!strcmp(mailfile, spoolfile))
  1313. X    spool_size = buf.st_size;
  1314. X    if (buf.st_size > last_size) {
  1315. X    last_size = buf.st_size;
  1316. X    return 1;
  1317. X    }
  1318. X    return 0;
  1319. X}
  1320. X
  1321. void
  1322. mail_status(as_prompt)
  1323. X{
  1324. X    static char buf[256];
  1325. X    register int cnt = 0, new = 0, unread = 0, deleted = 0;
  1326. X
  1327. X    for ( ; cnt < msg_cnt; cnt++) {
  1328. X    if (ison(msg[cnt].m_flags, UNREAD))
  1329. X        unread++;
  1330. X    if (ison(msg[cnt].m_flags, DELETE))
  1331. X        deleted++;
  1332. X    if (isoff(msg[cnt].m_flags, OLD))
  1333. X        new++;
  1334. X    }
  1335. X    if (as_prompt) {
  1336. X    register char *p, *b = buf;
  1337. X    for (p = prompt; *p; p++)
  1338. X        if (*p == '\\')
  1339. X        switch (*++p) {
  1340. X            case 'n': case 'r': *b++ = '\n';
  1341. X            when 't': *b++ = '\t';
  1342. X            otherwise: *b++ = *p;
  1343. X        }
  1344. X        else if (*p == '%')
  1345. X        switch (*++p) {
  1346. X            case 'm':
  1347. X            b += strlen(sprintf(b,"%d",(msg_cnt)? current_msg+1:0));
  1348. X            when 't':
  1349. X            b += strlen(sprintf(b, "%d", msg_cnt));
  1350. X            when 'd':
  1351. X            b += strlen(sprintf(b, "%d", deleted));
  1352. X            when 'u':
  1353. X            b += strlen(sprintf(b, "%d", unread));
  1354. X            when 'n':
  1355. X            b += strlen(sprintf(b, "%d", new));
  1356. X            when 'f':
  1357. X            b += Strcpy(b, mailfile);
  1358. X            if (ison(glob_flags, READ_ONLY))
  1359. X                b += Strcpy(b, " [read only]");
  1360. X            when 'T': case 'D': case 'Y': case 'M': case 'N':
  1361. X            b += Strcpy(b, Time(p, (long)0));
  1362. X            otherwise: *b++ = *p;
  1363. X        }
  1364. X        else if (*p == '!')
  1365. X        b += strlen(sprintf(b, "%d", hist_no+1));
  1366. X        else
  1367. X        *b++ = *p;
  1368. X    *b = 0;
  1369. X    print("%s", buf); /* buf MIGHT have a % in it... don't pass as fmt */
  1370. X    return;
  1371. X    }
  1372. X    (void) sprintf(buf,"\"%s\"%s: %d message%s, %d new, %d unread",
  1373. X    mailfile, ison(glob_flags, READ_ONLY)? " [read only]" : "",
  1374. X    msg_cnt, (msg_cnt != 1)? "s": NO_STRING, new, unread);
  1375. X    if (istool || iscurses)
  1376. X    (void) sprintf(buf+strlen(buf), ", %d deleted", deleted);
  1377. X#ifdef SUNTOOL
  1378. X    if (istool) {
  1379. X    static char ic_text[4];
  1380. X    extern struct pixrect mail_icon_image1, mail_icon_image2;
  1381. X    (void) sprintf(ic_text, "%3d", msg_cnt);
  1382. X    tool_set_attributes(tool,
  1383. X        WIN_LABEL, buf,
  1384. X        WIN_ICON_LABEL, ic_text,
  1385. X        WIN_ICON_IMAGE, ison(glob_flags, NEW_MAIL)?
  1386. X        &mail_icon_image2 : &mail_icon_image1,
  1387. X        0);
  1388. X    } else
  1389. X#endif /* SUNTOOL */
  1390. X#ifdef CURSES
  1391. X    if (iscurses)
  1392. X        mvprintw(0, 0, "%-3d %-.*s",
  1393. X        ((msg_cnt)? current_msg+1 : 0), COLS-5, buf), clrtoeol();
  1394. X    else
  1395. X#endif /* CURSES */
  1396. X        puts(buf);
  1397. X    return;
  1398. X}
  1399. X
  1400. X/* return -1 since function doesn't affect messages */
  1401. check_flags(flags)
  1402. u_long flags;
  1403. X{
  1404. X    print_more(" ");
  1405. X    if (ison(flags, VERBOSE))
  1406. X    print_more("VERBOSE ");
  1407. X    if (ison(flags, INCLUDE))
  1408. X    print_more("INCLUDE ");
  1409. X    if (ison(flags, INCLUDE_H))
  1410. X    print_more("INCLUDE_H ");
  1411. X    if (ison(flags, EDIT))
  1412. X    print_more("EDIT ");
  1413. X    if (ison(flags, SIGN))
  1414. X    print_more("SIGN ");
  1415. X    if (ison(flags, DO_FORTUNE))
  1416. X    print_more("DO_FORTUNE ");
  1417. X    if (ison(flags, NO_HEADER))
  1418. X    print_more("NO_HEADER ");
  1419. X    if (ison(flags, DELETE))
  1420. X    print_more("DELETE ");
  1421. X    if (ison(flags, OLD))
  1422. X    print_more("OLD ");
  1423. X    if (ison(flags, UNREAD))
  1424. X    print_more("UNREAD ");
  1425. X    if (ison(flags, UPDATE_STATUS))
  1426. X    print_more("UPDATE_STATUS ");
  1427. X    if (ison(flags, NO_PAGE))
  1428. X    print_more("NO_PAGE ");
  1429. X    if (ison(flags, INDENT))
  1430. X    print_more("INDENT ");
  1431. X    if (ison(flags, NO_IGNORE))
  1432. X    print_more("NO_IGNORE ");
  1433. X    if (ison(flags, PRESERVE))
  1434. X    print_more("PRESERVE ");
  1435. X    print_more("\n");
  1436. X    return -1;
  1437. X}
  1438. END_OF_FILE
  1439. if test 19132 -ne `wc -c <'msgs.c'`; then
  1440.     echo shar: \"'msgs.c'\" unpacked with wrong size!
  1441. fi
  1442. # end of 'msgs.c'
  1443. fi
  1444. echo shar: End of archive 7 \(of 14\).
  1445. cp /dev/null ark7isdone
  1446. MISSING=""
  1447. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1448.     if test ! -f ark${I}isdone ; then
  1449.     MISSING="${MISSING} ${I}"
  1450.     fi
  1451. done
  1452. if test "${MISSING}" = "" ; then
  1453.     echo You have unpacked all 14 archives.
  1454.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1455. else
  1456.     echo You still need to unpack the following archives:
  1457.     echo "        " ${MISSING}
  1458. fi
  1459. ##  End of shell archive.
  1460. exit 0
  1461.